﻿using System;
using System.Net;
using System.Web;
using System.Globalization;
using Stimulus360.Models.Data;
using Stimulus360.Repositories;
using Microsoft.ServiceModel.Web;
using System.Collections.Generic;
using Stimulus360.Services.Interfaces;
using Stimulus360.Repositories.Interfaces;
using Stimulus360.Models.Data.CustomTypes;

namespace Stimulus360.Services
{

    /// <summary>
    ///     This class interacts with IAnalyticsRepository for retrieving analytics information
    ///     to be shown in the graphs
    /// </summary>
    public class AnalyticsService : IAnalyticsService
    {
        #region IAnalyticsService Members

        /// <summary>
        ///     Instance of AnalyticsRepository to be used
        /// </summary>
        private readonly IAnalyticsRepository _analyticsRepository;

        /// <summary>
        ///     Default constructor. Creates an instance of the Analytics Repository to be used
        /// </summary>
        public AnalyticsService()
        {
            try
            {
                _analyticsRepository = new AnalyticsRepository();

            }
            catch (NullReferenceException exception)
            {
                // Exception conditions detected when invoking this service as a RESTFul service need to report an HTTP status code in the 
                //  400-500   range in addition to a message that details the exception
                throw new WebProtocolException(HttpStatusCode.BadGateway, "Could not connect to the database.Please check the connection and try again", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }

        }

        /// <summary>
        ///     Dependency Injection Enabled constructor.Sets the IAnalyticsRepository instance
        /// </summary>
        /// <param name="repository">
        ///     The IAnalyticsRepository instance to be used
        /// </param>
        public AnalyticsService(IAnalyticsRepository repository)
        {
            try
            {
                _analyticsRepository = repository;

            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to retrieve the Budget , Spend and Job Count details for the top N 
        ///     investment categories
        /// </summary>
        /// <param name="top">
        ///     The No of categories to be considered
        /// </param>
        /// <returns>
        ///     The Budget , Spend and Job Count details for the top N 
        ///     investment categories
        /// </returns>
        public ICollection<BudgetSpendSummary> GetTopNBudgetSpendSummaries(string top)
        {
            try
            {
                top = HttpUtility.HtmlEncode(top);
                return _analyticsRepository.GetTopNBudgetSpendSummaries(top.ToInt());

            }
            catch (ArgumentNullException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "Ranking provided is null", exception);
            }
            catch (FormatException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "Ranking provided is in invalid format",
                                               exception);
            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "The Database context was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to retrieve the Idea trend for the current financial year
        /// </summary>
        /// <returns>
        ///     The Idea trend for the current financial year
        /// </returns>
        public ICollection<IdeaTrend> GetIdeationTrend()
        {
            try
            {
                return _analyticsRepository.GetIdeationTrend();

            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "The Database context was null", exception);
            }

            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to retrieve the Project trend for the current financial year
        /// </summary>
        /// <returns>
        ///     The Project  trend for the current financial year
        /// </returns>
        public ICollection<ProjectTrend> GetProjectTrend()
        {
            try
            {
                return _analyticsRepository.GetProjectTrend();

            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "The Database context was null", exception);
            }

            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to retrieve the summary shown on the Home page
        /// </summary>
        /// <returns>
        ///     The summary shown on the Home page
        /// </returns>
        public HomeViewSummary GetHomeViewSummary()
        {
            try
            {
                HomeViewSummary summary = new HomeViewSummary();
                summary.Budget = _analyticsRepository.GetStimulusBudget();
                summary.Spend = _analyticsRepository.GetBudgetSpent();
                summary.CommunityParticipation = CalculateCommunityParticipation();
                summary.JobsCreated = _analyticsRepository.GetJobsCreated();
                summary.ProjectsExecuted = _analyticsRepository.GetProjectExecutedCount().ToString(CultureInfo.CurrentCulture);
                return summary;
            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "The Database context was null", exception);
            }

            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }



        /// <summary>
        ///     Method to get the percentage of active participants vs total participants in the community
        /// </summary>
        /// <returns>
        ///     The percentage of active participants vs total participants in the community
        /// </returns>
        public string CalculateCommunityParticipation()
        {
            try
            {

                int activeUsers = _analyticsRepository.GetActiveUsers().Count;
                int totalUsers = _analyticsRepository.GetAllUserCount();
                decimal percentage = ((decimal)activeUsers / (decimal)totalUsers) * 100;
                percentage = Math.Round(percentage, 2);
                return percentage.ToString(CultureInfo.CurrentCulture) + "%";
            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "The Database context was null", exception);
            }

            catch (DivideByZeroException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "Invalid Condition:- User count was 0.", exception);
            }

            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }



        #endregion


    }
}
